package org.kfish.framework;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.kfish.framework.bean.Data;
import org.kfish.framework.bean.Handler;
import org.kfish.framework.bean.Param;
import org.kfish.framework.bean.View;
import org.kfish.framework.helper.BeanHelper;
import org.kfish.framework.helper.ConfigHelper;
import org.kfish.framework.helper.ControllerHelper;
import org.kfish.framework.helper.EmbeddedConfigHelper;
import org.kfish.framework.helper.RequestHelper;
import org.kfish.framework.helper.ServletHelper;
import org.kfish.framework.helper.UploadHelper;
import org.kfish.framework.util.JsonUtil;
import org.kfish.framework.util.ReflectionUtil;
import org.kfish.framework.util.StringUtil;

/**
 * 请求转发器
 * 
 * @author CK
 *
 */
@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class Dispatcher extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		// 初始化相关Helper类
		HelperLoader.init();
		// 获取 ServletContext 对象（用于注册Servlet)
		ServletContext servletContext = servletConfig.getServletContext();
		// 初始化UploaderHelper
		UploadHelper.init(servletContext);

		// 注册处理JSP 的 Servlet
		ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
		jspServlet.addMapping(ConfigHelper.getAppJspPath() + "*");
		// 注册处理静态资源的默认 Servlet
		ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
		defaultServlet.addMapping(ConfigHelper.getAppAssetPath() + "*");
	}

	@Override
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 初始化servlet helper
		ServletHelper.init(request, response);
		try {

			// 获取请求方法与请求路径
			String requestMethod = request.getMethod().toLowerCase();
			String requestPath = request.getPathInfo();
			// 获取Action 处理器
			Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
			// 如果有与之匹配的处理器
			if (handler != null) {
				// 获取控制器类和其实例
				Class<?> controllerClass = handler.getControllerClass();
				Object controllerBean = BeanHelper.getBean(controllerClass);
				// 创建param对象
				Param param;
				if (UploadHelper.isMultipart(request)) {
					param = UploadHelper.createParam(request);
				} else {
					param = RequestHelper.createParam(request);
				}

				// 调用 Action方法
				Method actionMethod = handler.getActionMethod();
				Object result;
				if (param.isEmpty()) {
					result = ReflectionUtil.invokeMethod(controllerBean, actionMethod);
				} else {
					result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
				}

				// 分情况处理结果
				if (result instanceof View) {
					handleViewResult((View) result, request, response);
				} else if (result instanceof Data) {
					handleDataResult((Data) result, response);
				}
			}else{
				//获取不到handler时的处理（404）	
				//response.sendRedirect("/main");
				View notFoundPage=  EmbeddedConfigHelper.getEmbeddedConfig().getErrorPage();
				if(notFoundPage!=null){
					handleViewResult(notFoundPage, request, response);
				}
			}
		} finally {
			ServletHelper.destroy();
		}

	}

	private static void handleViewResult(View view, HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		// 返回jsp页面
		String path = view.getPath();
		if (StringUtil.isNotEmpty(path)) {
			if (path.startsWith("/")) {
				response.sendRedirect(request.getContextPath() + path);
			} else {
				Map<String, Object> model = view.getModel();

				for (Entry<String, Object> entry : model.entrySet()) {
					request.setAttribute(entry.getKey(), entry.getValue());
				}

				request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request, response);
			}
		}
	}

	private static void handleDataResult(Data data, HttpServletResponse response) throws IOException {
		// 返回JSON数据
		Object model = data.getModel();
		if (model != null) {
			response.setContentType("application/json");
			response.setCharacterEncoding("UTF-8");
			try (PrintWriter writer = response.getWriter();) {
				String json = JsonUtil.toJson(model);
				writer.write(json);
			}
		}
	}

}
